
<?php
/**
 * 
 * @author nrnwest@gmail.com
 * 
 */
class Arm_Navigation
{

    /**
     * Ключ который содержит вложенные данные меню.
     */
    private  $_subCategory = 'pages';
    /**
     * Arm_Navigation_Sql_Pdo_Mysql
     * 
     * @var Arm_Navigation_Sql_Pdo_Mysql
     */
    private $_sql = null;
    
    /**
     * Данные по умолчанию для одного элемента меню
     * @var array
     */
    private $_defaulNode = array('target'=>null, 'class'=>null, 'resource'=>null, 'privilege'=>null, 'visible'=>1, 'title'=>null, 'uri'=>null, 'label'=>null);
    
    /**
     * Системные меню
     * @var array
     */
    private $_systemMenu = array();
    
    /**
     * Реестер обьектов Arm_Db_Nested
     * @var unknown_type
     */
    private static $_registerTree = array();
    
    /**
     * Arm_Filter_Url
     * @var Arm_Filter_Url
     */
    private $_urlFilter = null;
    
    /**
     * Системные структуры.
     * @var array
     */
    private $_structureSystem = array('user', 'admin');
    
    /**
     * Базовый урл.
     * @var string
     */
    private $_baseUri = null;
    
    /**
     * Конструктор.
     * @param string $subCategory Дочерние узлы будут содержаться в данном ключе
     */
    public function __construct($subCategory=null)
    {
     if($subCategory !== null) {
         $this->_subCategory = $subCategory;
     }
     $this->getSql();
     $this->_urlFilter = new Arm_Filter_Url();
     $baseUri = Zend_Controller_Front::getInstance()->getBaseUrl();
     if($baseUri !== '') {
         $this->_baseUri = $baseUri;
     }
    }
    
    /**
     * Вернет перечень системных меню в виде масива
     * 
     * @return array 
     */
    public function getSystemMenuName()
    {
       return $this->getSql()->getDb()->fetchCol($this->getSql()->getMenuSystemName());
    }
    
    /**
     * Вернет названия системных структур.
     * 
     * @return array
     */
    public function getSystemStructure()
    {
        return $this->_structureSystem;
    }
    
    /**
     * Вернет масив меню которые не являеються системными структурами.
     * 
     * @return array
     */
    public function  getMenusNotSystemStructure()
    {
      $menu   = $this->getMenuAllInfo();
      $system = $this->getSystemStructure();
      $result = array();
      foreach ($menu as $k=>$v) {
          if(array_search($v['label'], $system) === false) {
              $result[] = $v;
          }
      }
      return $result;
    }
    
    /**
     * Вернет информацию про все меню в системе
     *
     * @return array
     */
    public function getMenuAllInfo()
    {
        return $this->getSql()->getDb()->fetchAll($this->getSql()->getMenuAllInfo());
    }
    
    /**
     * Вернет данные одного меню
     * 
     * @return array
     */
    public function getMenuInfo($idMenu)
    {
      return $this->getSql()->getDb()->fetchRow($this->getSql()->getMenuInfo($idMenu));
    }

    /**
     * Arm_Navigation_Sql_Pdo_Mysql
     *
     * @return Arm_Navigation_Sql_Pdo_Mysql
     */
    public function getSql()
    {
        if($this->_sql !== null) {
            return $this->_sql;
        }
       $this->_sql = Arm_Db::getSqlObject('Arm_Navigation_Sql', Arm_Db::getAdapter());
       return $this->_sql;
    }

   
    /**
     * Получения id узла по uri и имени меню
     * @param string $url
     * @param string $nameMenu
     */
    public function getIdNodeUrl($url, $nameMenu)
    {
       if($this->_baseUri !== null) {
           $url = str_replace($this->_baseUri, '', $url);
       }
       $url = $this->filterUri($url);
       $idMenu = $this->getIdMenu($nameMenu);
       return $this->getSql()->getIdNodeUrl($url, $idMenu);
    }
    
    /**
     * Если базовый урл не пустой он будет удален с $url
     * 
     * @param $url
     */
    public function delBaseUrl($url)
    {
         if($this->_baseUri !== null) {
           $url = str_replace($this->_baseUri, '', $url);
       }
      return $url;
    }
    
    /**
     * Вернет вседерево меню. 
     * @param string $name названия меню пример "user"
     * @param bool $notMultiArray если true вернет масив, но без вложенных суб директорий.
     * @return array вернет много мерный масив.
     */
    public  function getMenuDataTree($name, $notMultiArray = false)
    {     
        $idMenu = $this->getIdMenu($name); 
        if($idMenu === false) {
            throw new Arm_Navigation_Exception(Arm_Translate::_('Вы ошиблись при воде имени меню, его не существует в системе, вели "%s"', $name));
        }       
        $tree   = $this->_getTree($idMenu);
        $select = $tree->getTree();
        $select = $this->getSql()->addTableDataTranslate($select);
        $data   = $this->getSql()->getDb()->fetchAll($select);
        $this->_helperBaseUrl($data);
        if($notMultiArray === true) {
            return $data;
        }
        return $tree->getArray($data, $this->_subCategory);
    }
    
    /**
     * Получения карты пользовательского интерфейса или меню
     * @param string $interface user|admin
     */
    public function getMenuDataMapa($interface='user', $returnSelect = false)
    {
        if($interface !== 'user' and $interface !== 'admin') {
            throw new Arm_Navigation_Exception(Arm_Translate::_('Не верно указан интерфейс, допустимые значения user|admin
            вы вели "%s"', $interface));
        }
         $result = $this->getSql()->getMenuDataMapa($interface, $returnSelect);
        
         if($returnSelect) {
             return $result;
         }
         $menus = $this->getMenuAllInfo();
         $tree = $this->_getTree($menus[0]['id']);
         return  $tree->getArray($result);
    }
    
    /**
     * Добавления базового урла.
     * @param array $data
     */
    protected function _helperBaseUrl(&$data)
    {
       foreach ($data as $k => $v) {
           $v['uri'] = $this->_baseUri . $v['uri'];
           $data[$k] = $v;
       }
       return; 
    }

  
    
    /**
     * Вернет приоктрытое дерево
     * 
     * @param int|null $idNode id актиновго элемента меню, или null если нужно получить не раскрытое меню.
     * @param bool $notMultiArray если true вернет масив, но без вложенных суб директорий.
     * @return array
     */
    public  function getMenuDataOpen($idNode=null, $menu=null, $notMultiArray = false)
    {        
        if($idNode === null and $menu === null) {
            throw new Arm_Navigation_Exception(Arm_Translate::_('Вы должны указать $idNode or $menu'));
        }
        if($idNode === null) {
            $idMenu = $this->getIdMenu($menu);
            if($idMenu === false) {
                throw new Arm_Navigation_Exception(Arm_Translate::_('Не существует меню %s', array($menu)));
            }
            $tree   = $this->_getTree($idMenu);
            $select = $tree->getChildren($tree->getRootId());
        } else {       
            $idMenu = $this->getSql()->getIdMenuNode($idNode);
            $tree   = $this->_getTree($idMenu);
            $select = $tree->getOpenTree($idNode);
        }

        $select = $this->getSql()->addTableDataTranslate($select);
        $data   = $this->getSql()->getDb()->fetchAll($select);
        
        $this->_helperBaseUrl($data);
        if($notMultiArray === true) {
            return $data;
        }
        return $tree->getArray($data, $this->_subCategory);
    }
    
    /**
     * Вернет путь к активному элементу
     * 
     * @param int $idNode id актиновго элемента меню
     * @param bool $notMultiArray если true вернет масив, но без вложенных суб директорий.
     * @return array 
     */
    public function getMenuDataPath($idNode, $notMultiArray = false)
    {
        $idMenu = $this->getSql()->getIdMenuNode($idNode);        
        $tree   = $this->_getTree($idMenu);
        $select = $tree->getPath($idNode);
        $select = $this->getSql()->addTableDataTranslate($select);
        $data   = $this->getSql()->getDb()->fetchAll($select);
        $this->_helperBaseUrl($data);
        if($notMultiArray === true) {
            return $data;
        }
        return $tree->getArray($data, $this->_subCategory);
    }
    
    /**
     * Вернет детей узла $idNode
     * @param bool $notMultiArray если true вернет масив, но без вложенных суб директорий.
     * @param int $idNode
     */
    public function getMenuDataChildren($idNode, $notMultiArray = false)
    {
      $idMenu = $this->getSql()->getIdMenuNode($idNode);        
      $tree   = $this->_getTree($idMenu);
      $select = $tree->getChildren($idNode);
      $select = $this->getSql()->addTableDataTranslate($select);
      $data   = $this->getSql()->getDb()->fetchAll($select);
        $this->_helperBaseUrl($data);
        if($notMultiArray === true) {
            return $data;
        }
        return $tree->getArray($data, $this->_subCategory);
    }
    
    /**
     * Создвания меню на основе масива, если меню не существует будет брошено исключение
     * 
     * @param array $data данные для записи в меню
     * @param string $name имя меню
     * @param int|null $idModule если не указно id Модуля будет высчитан по id меню.
     * @param bool $up если false будет добавленно последним, если true первым.
     */
    public function writeMenu($name, $data, $idModule = null, $up=false)
    {
      
       $idMenu = $this->getIdMenu($name);
       
       if($idModule === null) {
       $menuinfo = $this->getMenuInfo($idMenu);
       $idModule = $menuinfo['id_module'];
       }
       $idLang  = Arm_Translate::getInstance()->getIdLangDefault();
       if($idMenu === false) {
           throw new Arm_Navigation_Exception('Не существует меню:' . $name);
       }
       $tree = $this->_getTree($idMenu);
       try { 
           $rootId = $tree->getRootId();
       }catch (Exception $e) {
           $rootId = $tree->createRootNode();
           
       }
       try {
       $this->getSql()->getDb()->beginTransaction();
     
       $arrayNode = $tree->createNodes($rootId, $data, $this->_subCategory, $up);
       // подготовим масив для записи
         
       $this->_prepareArrayDataTranslate($arrayNode, $idModule, $idLang);
       
       // запишем в таблицу данных и переводов.
           $this->getSql()->writeMenu($arrayNode);
           $this->getSql()->getDb()->commit();
       } catch (Exception $e) {
                  $this->getSql()->getDb()->rollBack();
                  $eStr = $e->__toString();
                  throw new Arm_Exception(Arm_Translate::_('Произошла ошибка при установки меню "%s" id модуля "%s" данные меню %s ошибка %s', array($name, $idModule, print_r($data, true), $eStr)));
       }
    }
    
    /**
     * Запись масива формата ZF Navigation как дочерние элементы определеного $idNode
     * @param int   $idParent id главный раздел
     * @param array $data
     * @params bool $up если false устанавливаем вставляемые узлы в самую нижнею позицию, если true то верх
     */
    public function writeChildersNodeArray($idParent, $data, $up=false)
    {
        $idMenu = $this->getSql()->getIdMenuNode($idParent);
        $menuinfo = $this->getMenuInfo($idMenu);
        $idModule = $menuinfo['id_module'];
        $idLang  = Arm_Translate::getInstance()->getIdLangDefault();
        
       $tree = $this->_getTree($idMenu);
       try {
       $this->getSql()->getDb()->beginTransaction();
       $arrayNode = $tree->createNodes($idParent, $data, $this->_subCategory, $up);
       // подготовим масив для записи
       $this->_prepareArrayDataTranslate($arrayNode, $idModule, $idLang);
       // запишем в таблицу данных и переводов.
           $this->getSql()->writeMenu($arrayNode);
           $this->getSql()->getDb()->commit();
       
       } catch (Exception $e) {
                  $this->getSql()->getDb()->rollBack();
                  throw $e;
       }
    }
    
    /**
     * Помощник создает масив для записи в таблицу данных, и таблицу переводов, при записи массива
     * в меню.
     * @param unknown_type $arrayNode
     * @param unknown_type $idModule
     * @param unknown_type $idLang
     */
    protected function _prepareArrayDataTranslate(&$arrayNode, $idModule, $idLang)
    {
      // получаем последний id с таблицы данных.
      $id_data = $this->getSql()->getLastIdTableData();
      foreach ($arrayNode as $k=>$v) {
          $arrayNode[$k] = $this->valdateFilterDataNode($arrayNode[$k]);
          $id_data++;
          $arrayNode[$k]['id_data']           = $id_data;
          $arrayNode[$k]['id_structure']      = $v['id'];
          $arrayNode[$k]['id_node_translate'] = $id_data;
          $arrayNode[$k]['id_module']         = $idModule;
          $arrayNode[$k]['id_lang']           = $idLang;
      }
      return;
    }
    

    
    /**
     * Вернет данные одного узла меню.
     * @param int $id
     * @return array
     */
    public function getNodeData($id)
    {
        return $this->getSql()->getDb()->fetchRow($this->getSql()->getNodeData($id));
    }
    
  

    /**
     * Обновления пункта меню. Обновляет данные в таблице данных и данные в таблице переводов
     * @param int $idNode id пункта 
     * @param array $data
     */
    public function updateNode($idNode, $data)
    {
        $this->getSql()->updateNode($idNode, $data);
        return;
    }


    
    /**
     * Вернет id меню по его названию.
     * 
     * @param string $name названия меню.
     * @return int|false
     */
    public function getIdMenu($name)
    {
        $name = strtolower(trim($name));
        return $this->getSql()->getIdMenu($name);
    }
    
    /**
     * Оновления данных меню, названия, описание, модуль, и так дальше.
     * @param int $idMenu
     * @param array $data
     */
    public function updateMenu($idMenu, $data)
    {
         return $this->getSql()->updateMenu($idMenu, $data);
    }
    
    /**
     * Удаляет все данные меню по его id
     * @param int $idMenu
     */
    public function delMenu($idMenu)
    {
        return $this->getSql()->delMenu($idMenu, $this->_getTree($idMenu));
    }
    
    /**
     * Удаления меню, определеного модуля
     * 
     * @param int $idModule id Модуля
     */
    public function delMenuModule($idModule)
    {
       $this->getSql()->delMenuModule($idModule, $this);
    }

    /**
     * Создания пункта меню.
     * 
     * @param array $data данные для создания пункта меню
     * @param int|0 $idParent
     * @param int|0 $idMenu id меню, если не указан $idParent то id меню должно быть обязательно указано
     * @param int|0 $idModule id модуля в системе
     * return int id созданого узла.
     */
    public function createNode($data, $idParent = 0, $idMenu=0, $idModule=0)
    { 
        $data = $this->valdateFilterDataNode($data);
        $idParent = (int) $idParent;
        $idMenu   = (int) $idMenu;
        if($idParent === 0 and $idMenu ===0) {
            throw new Arm_Navigation_Exception(Arm_Translate::_('Вы должны указать id меню если это корневой раздела меню'));
        }
        if($idMenu === 0) {
            $idMenu = $this->getSql()->getIdMenuNode($idParent);
        }
        $tree = $this->_getTree($idMenu);
        try {
        $this->getSql()->getDb()->beginTransaction();
        // id родителя это id дерева
        if($idParent === 0) {
            $idParent = $tree->getRootId();
        }
        $idNode = $tree->createNodeDown($idParent);
        $this->getSql()->createNode($idNode, $idModule, $data);
        $this->getSql()->getDb()->commit();
        } Catch(Exception $e) {
           $this->getSql()->getDb()->rollBack(); 
           throw $e;
        }
        return $idNode;
    }

    /**
     * Удаления узла.
     * @param int $idNode
     */
    public function delNode($idNode)
    {
        // Получения информации по узлу
        $data = $this->getNodeData($idNode);
        $tree = $this->_getTree($data['id_menu']);
        $tree->delete($idNode);
        $this->getSql()->deleteNode($data['id']);
        return $idNode;
    }

    /**
     * Создания меню. Меню может создаваться для определеного модуля, 
     * при удалении данное меню будет тоже удаленно, или проектное меню.
     * 
     * @param string $name Имя меню
     * @param string $title Описания меню на языке по умолчанию.
     * @param int|0  $idModule имя модуля если меню создаеться только для текущего проекта.
     * @return int вернет id меню в системе.
     */
    public function createMenu($name, $title, $idModule=0)
    {
        $name = strtolower(trim($name));
        // проверяем есть ли такое меню в системе.
        if(false !== $this->getIdMenu($name)) {
            throw new Arm_Navigation_Exception(Arm_Translate::_('Меню "%s" уже существует в системе', $name));
        }
        $idMenu = $this->getSql()->createMenu($name, $title, $idModule);
        $tree = $this->_getTree($idMenu);
        $tree->createRootNode();
        return $idMenu;
    }
    
    /**
     * Перемещения верх узла, на уровне братних узлов, на уровне текущего родителя
     * @param int $idNode
     */
    public function moveUpNode($idNode)
    {
      $idMenu = $this->getSql()->getIdMenuNode($idNode);
      $tree = $this->_getTree($idMenu);
      $tree->movingUp($idNode);
      return;
    }
    
    /**
     * Перемещения вниз узла, на уровне братних узлов, на уровне текущего родителя
     * @param int $idNode
     */
    public function moveDownNode($idNode)
    {
      $idMenu = $this->getSql()->getIdMenuNode($idNode);
      $tree = $this->_getTree($idMenu);
      $tree->movingDown($idNode);
      return;
    }
    
    /**
     * Перемещения узла, к новому родителю, узел становиться самим верхним дочерним элементом нового родителя.
     * @param int $idNode id узла
     * @param int $idParentNew id нового родителя
     */
    public function moveNode($idNode, $idParentNew)
    {
      $idParentNew = (int) $idParentNew;  
      $idMenu = $this->getSql()->getIdMenuNode($idNode);
      $tree = $this->_getTree($idMenu);
      // проверим что новый родитель не совпадает с старым.
      $res =  $tree->getParent($idNode, true);
      $res['id'] = (int) $res['id'];
      if($res['id'] === $idParentNew) {
          throw new Arm_Navigation_Exception('вы указали id не нового родителя для узла а id текущего родителя: ' . $idParentNew);
      }
      $tree->movingUnderUp($idNode, $idParentNew); 
      return;
    }

    /**
     * Вернет обьект Arm_Db_Tree_Nested
     *
     * @param int $idMenu
     * @return Arm_Db_Tree_Nested
     */
    public  function _getTree($idMenu)
    {
        $idMenu = (int) $idMenu;
        if(array_key_exists($idMenu, self::$_registerTree)) {
            return self::$_registerTree[$idMenu];
        }
        $tree = new Arm_Db_Tree_Nested(Arm_Navigation_Sql_Pdo_Mysql::ADMIN_NAVIGATION, $this->getSql()->getDb(), $idMenu);
        $tree->getParams()->setColumnTreeID('id_menu');
        self::$_registerTree[$idMenu] = $tree;
        return self::$_registerTree[$idMenu];
    }
    
   
    
    /**
     * Валидация и фильтрация данных для записи узла навигации
     * @param array $data
     * @throw Arm_Navigation_Exception Если не сущестует ключа uri или label
     * @return array
     */
    public function valdateFilterDataNode($data)
    {
       $data = array_merge($this->_defaulNode, $data);
       if($data['uri'] === null) {
           throw new Arm_Navigation_Exception(Arm_Translate::_('Вы не указали uri в данных для узла в меню, данные: "%s"', print_r($data, true)));
       }
     if($data['label'] === null) {
           throw new Arm_Navigation_Exception(Arm_Translate::_('Вы не указали label в данных для узла в меню, данные: "%s"', print_r($data, true)));
       }
       $data['uri'] = $this->filterUri($data['uri']);
       $data['label'] = trim($data['label']);
       $data['title'] = trim($data['title']);
       return $data;
    }
    
    /**
     * Фильрация урла
     * @param string $url
     * @return string
     */
    public function filterUri($url)
    {
      return  $this->_urlFilter->filter($url);
    }
    
    /**
     * Установка всех меню модуля, если меню не существует в системе оно будет созданно.
     * Формат файлов для записи меню ZF-Navigation user.php
     * Если меню уже существуют для данного модуля то они будут удаленны перед записью.
     * 
     * @param string $module имя модуля
     * @param string|null $menuName если null устанавливаються все меню модуля или одно если оно укзано. 
     */
    public function setMenuModule($module, $menuName=null)
    {
      
      if($menuName === null) {
          // получаем все меню с директории
          $menus = Arm_Module::getInstance()->getNavigations($module, false);  
      } else {
          $menuName = strtolower($menuName);
          // проверим существует ли файл
          $pathMenu = Arm_Module::getInstance()->getPathMenu($module, $menuName);
          if(is_file($pathMenu) === false) {
              throw new Arm_Navigation_Exception(Arm_Translate::_('Не возможно прочитать файл меню "%s"', $pathMenu));
          }
          $menus = array($pathMenu);
      }
      // можем запускать цикл по записи меню
      // если меню не user или admin то записываеться id модуля который указан
      // иначе 0
      $idModule = Arm_Module::getInstance()->getIdModule($module); 
           
      
      foreach ($menus as $file) {
          $data = require $file; 
          $menuName = str_replace(Arm_Module::getInstance()->getTypeMenuFile(),'', basename($file));
           // проверка системное меню или нет
           if(array_search($menuName, $this->getSystemMenuName()) === false) {
               $idModuleMenu = $idModule;
           } else {
               $idModuleMenu = 0;
           }
           // проверим есть ли меню в системе, если нет создадим его
           $idMenu = $this->getIdMenu($menuName);
           if(false === $idMenu) {
             $idMenu =  $this->createMenu($menuName, $menuName, $idModuleMenu);
           } else {
               // Чистим пункты относительно id меню и id модуля.
               $this->deleteModuleSystemMenu($idModule, $idMenu); 
           }
           //  записываем меню
           $this->writeMenu($menuName, $data, $idModule);   
      }
       return;
    }
    
    /**
     * Удаления пунктов меню с системных меню. Определеного модуля.
     * Если idMenu не передали то удаляються со всех системных меню
     * Все пункты модуля.
     * @param int $idModule
     * @return int $idMenu id меню если нужно удалить, только с определеного меню.
     */
    public function deleteModuleSystemMenu($idModule, $idMenu = null)
    {

        if($idMenu !== null) {
            $this->getSql()->deleteNodesModule($idMenu, $idModule, $this->_getTree($idMenu));
            return;
        }

       $systemMenu = $this->getSystemMenuName();
       foreach ($this->getSystemMenuName() as $v) {
           $idMenu = $this->getIdMenu($v);
           if($idMenu === false) {
               continue;
           }
           $this->getSql()->deleteNodesModule($idMenu, $idModule, $this->_getTree($idMenu)); 
       }
       return;
    }
    
    /**
     * Проверка меню установлено для модуля или нет.
     * @param string $module имя модуля
     * @param string $menu имя меню
     */
    public function isInstallMenuModule($module, $menu)
    {
      return $this->getSql()->isInstallMenuModule($module, $menu);
    }
    
    /**
     * Записывает меню в директорию install модуля.
     * 
     * @param string $menu
     * @param string $module
     */
    public function writeMenuModule($menu, $module)
    {
      $idMenu = $this->getIdMenu($menu); 
        if($idMenu === false) {
            throw new Arm_Navigation_Exception(Arm_Translate::_('Вы ошиблись при воде имени меню, его не существует в системе, вели "%s"', $menu));
        }     
        $tree   = $this->_getTree($idMenu);
        $select = $tree->getTree();
        // собираем только пункты меню модуля.
        $idModule = Arm_Module::getInstance()->getInstance()->getIdModule($module);
        $select->where(Arm_Navigation_Sql_Pdo_Mysql::ADMIN_NAVIGATION_DATA . '.id_module = ?', $idModule);
        $select = $this->getSql()->addTableDataTranslate($select);
        $data = $this->getSql()->getDb()->fetchAll($select);
        $path = Arm_Core::getPathModule($module) . 'install/navigation/' . $menu . '.php';
        if($data === array()) {
            // просто удалим файл меню так как нет данных.
            if(true === is_file($path)) {
                unlink($path);
            }
            return;
        }
        $data = $tree->getArray($data, $this->_subCategory);
        $data = $this->_helperCreateData($data);
        $write = new Zend_Config_Writer_Array();
        $write->write($path, new Zend_Config($data));
        return;
    }
    
    /**
     * Запись меню модуля.
     * @param string $module
     */
    public function writeMenusModule($module)
    {
      $idModule = Arm_Module::getInstance()->getIdModule($module);
      $menus =  array_merge($this->_sql->getMenuModule($idModule), $this->_sql->getMenuSystem());
      foreach ($menus as $menu) {
          $this->writeMenuModule($menu, $module);
      }
      return;
    }
    
    
    /**
     * Помощник для создания файла навигации модуля.
     * @param array $data
     */
    protected function _helperCreateData(&$data)
    {
       $addColums = array('lang', 'uri', 'target', 'class', 'resource', 'privilege', 'visible', 'label', 'title', 'pages'); 
       foreach ($data as $k=>$v) {
           if($k === 'pages' and $v === array()) {
               unset($data[$k]);
               continue;
           }
           if(is_array($v) and $v !== array()) {
             $data[$k] =  $this->_helperCreateData($v);
           }
           if(array_search($k, $addColums) === false and 0 !== preg_match('~[^0-9]+~', $k)) {
               unset($data[$k]);
           }
       }
       return $data;
    }

    /**
     * @todo не нужный метод.
     * перемещения узла
     */
/*    public function move($parentNew, $idNode, $pos)
    {
 
        $pos = (int) $pos;
        $parentNew = (int) $parentNew;
        $idNode = (int) $idNode;
        // получаем обьект дерева.
        $idMenu = $this->getSql()->getIdMenuNode($idNode);
        $tree = $this->_getTree($idMenu);
        // высчитываем id братнего узла.
        if($parentNew === 0) {
            $select = $tree->getTree();
            $select->where('level=?', 1);
            $braser = $this->getSql()->getDb()->fetchAll($select);
           
        } else {
            $braser = $tree->getChildren($parentNew, true);
        }
        
        if($pos === 0) {
            if($braser === array()) {
                $tree->movingUnderDown($idNode, $parentNew);
                return;
            }
            // получаем первый братний id
            $idBraser = $braser[0]['id'];
            $tree->movingBrotherUp($idNode, $idBraser);
            return;
        }
        
        // есть pos надо найти предедущий.
        $idBraser = $this->_getIdBraser($braser, $pos, $idNode);
        
        $tree->movingBrotherDown($idNode, $idBraser);
        return;
    }*/
    
    /**
     * Высчитываем  будущею позицию элемента.
     */
/*    public function _getIdBraser($braser, $pos, $idNode)
    {
      
        foreach ($braser as $k=>$v) {
            $id = (int) $v['id'];
            if($id === $idNode) {
              $posEl = $k;
            }
        }
        if(isset($posEl) and $posEl>$pos) {
        $pos--;
        }
        
        if(isset($posEl) === false) {
            $pos--;
        }
        
        foreach ($braser as $k=>$v) {
            if($k === $pos) {
                return $v['id'];
            }
        }
        
        $end = array_pop($braser);
        return $end['id'];
    }*/
    
    
    
    
    
}
